// @Title  modbus_tcp.go
// @Description  使用modbusTCP进行数据采集
// @Author  IT搬运工
// @Update
package gather

import (
	"intelligentgateway/src/container"
	"intelligentgateway/src/server"
	"strconv"
	"time"

	"github.com/things-go/go-modbus"
)

// @title    CreateModbusTCPClient
// @description   建立modbus TCP
// @auth      IT搬运工             时间（2022/7/14）
// @param
// @return
func CreateModbusTCPClient(ip string, port uint16) modbus.Client {
	p := modbus.NewTCPClientProvider(ip + ":" + strconv.Itoa(int(port)))
	client := modbus.NewClient(p)
	err := client.Connect()
	if err != nil {
		timer := time.NewTimer(15 * time.Minute)
		for range timer.C {
			client := modbus.NewClient(p)
			err := client.Connect()
			if err == nil {
				//连接正常
				timer.Stop()
				return client
			}

		}
	}
	return client
}

//TCP采集器的基本信息
type CollectInfo struct {
	Ip   string
	Port uint16
	Sn   string

	ChannelId string
}

//开启所有的Modbus转protobuff的TCP
func StartModbus2ProtobuffCollect() {
	infoList := server.GetModbusTcpConfig()
	for _, info := range infoList {
		collectInfo := &CollectInfo{
			Ip:        info.Ip,
			Port:      uint16(info.Port),
			Sn:        info.Sn,
			ChannelId: info.ChannelId,
		}
		go startProtobuffTcpCollect(collectInfo)
	}
}

//开始启动Tcp采集
func startProtobuffTcpCollect(collect *CollectInfo) {
	//启动modbus TCP
	client := CreateModbusTCPClient(collect.Ip, uint16(collect.Port))

	//获取设备的modbus点表
	var pointItemMap = make(map[int]*server.ModbusPoint)
	itemList := server.GetDataTypeBySn(collect.Sn)
	if itemList == nil {
		client.Close()
		return
	}
	for _, mdp := range itemList {
		modbusPoint := server.GetPointsBySn(collect.Sn, mdp.DataType)
		if nil != modbusPoint {
			pointItemMap[mdp.DataType] = modbusPoint
		}
	}

	//没有配置点表
	if len(pointItemMap) == 0 {
		client.Close()
		return
	}

	//获取通道
	channel := container.GetDevChannel(collect.ChannelId)
	if nil == channel {
		//通道未开启，不进行采集
		client.Close()
		return
	}

	//发送A-BMS和堆HVM
	go SendABMSAndHVMData(pointItemMap[int(ABMS)], pointItemMap[int(ABMS)], client, channel, collect.ChannelId, collect.Sn)
}
